<template>
  <el-dialog
    top="6vh"
    class="img-library"
    ref="imgUpload"
    :visible.sync="show"
    center
    title="公共图片库"
    width="60%"
    :before-close="handleCloseDialog"
  >
    <div class="top-wrapper">
      <el-form :model="filters" inline ref="searchForm">
        <el-form-item prop="businessId" v-show="userRole != 3">
          <el-select
            v-model="filters.businessId"
            size="mini"
            placeholder="请选择商户"
            clearable
            filterable
          >
            <el-option
              v-for="item in businessList"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item prop="content">
          <el-input
            v-model="filters.content"
            size="mini"
            placeholder="请输入文件名"
            clearable
            filterable
          >
          </el-input>
        </el-form-item>
        <el-form-item v-show="userRole != 3">
          <el-button type="primary" size="mini" @click="onSearch">
            查询
          </el-button>
          <el-button size="mini" @click="resetForm">
            重置
          </el-button>
        </el-form-item>
        <el-form-item>
          <el-upload
            @click.native="selectNativeImg"
            :disabled="selectedImgList.length == limit"
            ref="upload"
            action="#"
            :accept="acceptFile"
            :http-request="uploadImage"
            :on-exceed="handleExceed"
            :auto-upload="false"
            :on-change="fileChange"
            :limit="limitNum"
            :before-upload="beforeUpload"
            :multiple="limitNum > 1 ? true : false"
            :show-file-list="false"
          >
            <el-button slot="trigger" type="danger" size="mini">
              选择本地图片
            </el-button>
          </el-upload>
        </el-form-item>
        <el-tabs v-model="filters.type" @tab-click="handleTabChange" v-if="!fileType">
          <el-tab-pane label="图片" name="1"></el-tab-pane>
          <el-tab-pane label="视频" name="2"></el-tab-pane>
        </el-tabs>
      </el-form>
      <div
        v-show="selectedImgList.length > 0"
        class="selected-img"
        @click="handleShowDrawer"
      >
        <i class="el-icon-picture">
          <span class="dot">{{ selectedImgList.length }}</span>
        </i>
      </div>
    </div>
    <div class="img-container">
      <div
        class="img-list"
        v-loading="loading"
        element-loading-text="数据加载中，请稍后...">
        <div v-for="(item, index) in list">
          <div
            class="img-wrapper"
            :style="{ outline: existImg(item) ? '5px solid #07C160' : '' }"
            v-if="item.type == 1"
            :key="item.imageId"
          >
            <el-image
              ref="elImage"
              :src="item.url"
              fit="cover"
              :preview-src-list="formatUrl(list)"
            >
            </el-image>
            <div class="menu">
              <div
                @click="hanldeSelectImg(item)"
                :title="existImg(item) ? '移除' : '添加'"
              >
                <i v-if="existImg(item)" class="el-icon-remove-outline"></i>
                <i v-else class="el-icon-circle-plus-outline"></i>
              </div>
              <div @click="handlePreviewImg('elImage', index)" title="预览图片">
                <i class="el-icon-zoom-in"></i>
              </div>
            </div>
            <div v-show="existImg(item)" class="check-wrapper">
              <i class="el-icon-check"></i>
            </div>
          </div>
          <div
            class="video-wrapper"
            :style="{ outline: existImg(item) ? '5px solid #07C160' : '' }"
            v-else="item.type == 2"
          >
            <video
              :ref="'video' + index"
              controls
              width="100%"
              height="100%"
              :src="item.url"
            >
              <h2>我们很抱歉，您的浏览器<strong>不支持video标签</strong></h2>
              <a href="https://www.google.cn/chrome/">点击这里下载浏览器</a>
            </video>
            <div
              class="operate"
              @click="hanldeSelectImg(item)"
              :title="existImg(item) ? '移除' : '添加'"
            >
              <i v-if="existImg(item)" class="el-icon-remove-outline"></i>
              <i v-else class="el-icon-circle-plus-outline"></i>
            </div>
            <div v-show="existImg(item)" class="check-wrapper">
              <i class="el-icon-check"></i>
            </div>
          </div>
          <div class="text">
            {{ item.content }}
          </div>
        </div>
        <div class="empty" v-show="list.length == 0">
          对不起，没有找到相关数据！
        </div>
      </div>
    </div>
    <el-pagination
      background
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="page.pageNo"
      :page-sizes="[40, 100, 200]"
      :page-size="page.pageSize"
      layout="total, sizes, jumper, next, pager, prev"
      :total="page.pageTotal"
    ></el-pagination>
    <div slot="footer">
      <el-button type="primary" @click="handleConfirm">
        确定
      </el-button>
      <el-button @click="handleClear">
        重选
      </el-button>
    </div>
    <el-drawer append-to-body :visible.sync="showDrawer" :with-header="false">
      <div class="drawer-wrapper">
        <div class="cancel-back" @click="showDrawer = false">
          <i class="el-icon-arrow-right"></i>
        </div>
        <div class="header">
          选择的图片
        </div>
        <div class="img-list">
          <draggable
            class="draggable"
            v-model="selectedImgList"
            animation="300"
          >
            <div v-for="(item, index) in selectedImgList">
              <div
                class="img-wrapper"
                v-if="item.type == 1"
                :key="item.imageId"
              >
                <el-image
                  ref="elImage2"
                  :preview-src-list="formatUrl(selectedImgList)"
                  :src="item.url"
                  fit="cover"
                >
                </el-image>
                <div class="menu">
                  <div @click="hanldeSelectImg(item)" title="移除图片">
                    <i class="el-icon-remove-outline"></i>
                  </div>
                  <div
                    @click="handlePreviewImg('elImage2', index)"
                    title="预览图片"
                  >
                    <i class="el-icon-zoom-in"></i>
                  </div>
                </div>
              </div>
              <div class="video-wrapper" v-else="item.type == 2">
                <video
                  :ref="'video' + index"
                  controls
                  width="100%"
                  height="100%"
                  :src="item.url"
                >
                  <h2>
                    我们很抱歉，您的浏览器<strong>不支持video标签</strong>
                  </h2>
                  <a href="https://www.google.cn/chrome/">点击这里下载浏览器</a>
                </video>
                <div
                  class="operate"
                  @click="hanldeSelectImg(item)"
                  title="移除视频"
                >
                  <i class="el-icon-remove-outline"></i>
                </div>
              </div>
              <div class="text">{{ item.content }}</div>
            </div>
          </draggable>
        </div>
      </div>
    </el-drawer>
  </el-dialog>
</template>

<script>
import * as Constants from "@/constants/constants";
import ComponentApi from "@/api/components/component";
import BusinessApi from "@/api/business/business";
import CommonImage from "@/api/goods/commonImage";
import { nanoid } from "nanoid";
import { throttle } from "lodash-es";
import draggable from "vuedraggable";
export default {
  components: {
    draggable
  },
  props: {
    show: {
      type: Boolean,
      default: false
    },
    folder: {
      // 上传至OSS的文件夹路径
      type: String,
      default:"common"// 默认上传路径
    },
    limit: {
      type: Number,
      default: 5
    },
    fileType:{
      // 类型 1表示图片 2表示只能选择视频 空表示都可以选择
      type:String|Number,
    }
  },
  data() {
    return {
      filters: {
        businessId: "",
        content: "",
        type: "1"
      },
      page: {
        pageNo: 1,
        pageSize: 40,
        pageTotal: 0,
        totalPage: 0
      },
      imgFile: ".png,.jpg,.jpeg,.bmp,.png",
      videoFile: ".mp4,.m2v,.mkv",
      showDrawer: false,
      // 上传的本地图片长度
      startUploadLength: 0,
      // 选择本地图片的长度,这个主要是为了判断是否上传完成
      endUploadLength: 0,
      // 上传选择的图片
      selectedImgList: [],
      // 选中的图片列表
      formatSelectedList: [],
      multiple: false,
      list: [],
      showPreview: false,
      businessList: [],
      userRole: "",
      loading: false
    };
  },
  watch: {
    show(val) {
      if (val) {
        this.selectedImgList = [];
        this.startUploadLength = 0;
        this.endUploadLength = 0;
        this.page.pageNo = 1;
        this.page.Total = 0;
        this.filters.businessId = "";
        this.filters.type = this.fileType||"1";
        this.listData();
      }
    }
  },
  computed: {
    limitNum() {
      return this.limit - this.selectedImgList.length;
    },
    acceptFile() {
      return this.imgFile + "," + this.videoFile;
    }
  },
  mounted() {
    ComponentApi.uploadOss().then(async res => {
      this.ossClient = (await import('ali-oss')).default({
        region: Constants.OSS_REGION,
        accessKeyId: res.data.accessKeyId,
        accessKeySecret: res.data.accessKeySecret,
        stsToken: res.data.securityToken,
        bucket: Constants.OSS_BUCKET
      });
    });
    this.userRole = this.$store.getters["userRole"];
    if (this.userRole != 3) {
      this.getBusinessList();
    }
  },
  methods: {
    // 获取商户列表
    getBusinessList() {
      BusinessApi.listIdNameVo().then(res => {
        this.businessList = res.data;
      });
    },
    handleTabChange() {
      this.listData();
    },
    selectNativeImg() {
      if (this.selectedImgList.length == this.limit) {
        this.$message.error("最多只可以选择" + this.limit + "张图片或视频");
      }
    },
    // 判断图片是否已经选中
    existImg(val) {
      return this.selectedImgList.some(item => item.imageId == val.imageId);
    },
    // 把图片的数组对象里面的图片地址全部拿出来
    formatUrl(val) {
      return val.filter(item => item.type == 1).map(item => item.url);
    },
    // 确认选择
    handleConfirm() {
      if (this.selectedImgList.length <= 0) {
        this.$message.error("请选择");
        return;
      }
      let val = [...this.selectedImgList];
      val.forEach(item => {
        if (item.isUpload) {
          delete item.isUpload;
          delete item.imageId;
        }
      });
      this.$emit("getUrlList", val);
    },
    // 重选
    handleClear() {
      this.selectedImgList = [];
    },
    // 关闭
    handleCloseDialog() {
      this.$emit("cancel");
    },
    // 选择本地文件
    fileChange(file) {
      if (file.status == "ready") {
        this.startUploadLength++;
        this.$refs.upload.submit();
        this.$refs.upload.clearFiles();
      }
    },
    // 超出限制
    handleExceed() {
      this.$message.error(
        "最多可以选择" +
          this.limit +
          "张图片或者视频，你已经选择了" +
          this.selectedImgList.length +
          "张，还可以选择" +
          this.limitNum +
          "张图片或视频"
      );
    },
    // 上传之前
    beforeUpload(val) {
      if (val.size / 1024 / 1024 > 5) {
        this.$message.error("大小不能超过5MB");
        return false;
      } else {
        return;
      }
    },
    // 上传图片
    async uploadImage(option) {
      // 每一次都需要清空
      // this.$refs.upload.clearFiles()
      try {
        const _this = this;
        // 当前上传的文件
        let file = option.file;
        const fileName = file.name;
        const fileType = fileName.split("\.")[1];
        const newName = _this.$Utils.mathRand19() + "." + fileType;
        const storeAs = Constants.OSS_WEB_URL + _this.folder + "/" + newName;
        //console.log('开始上传，文件名>>>>>' + fileName)
        // TODO 测试 注释上传动作
        _this.ossClient
          .put(storeAs, file, {})
          .then(function(ret) {
            if (ret.res.statusCode === 200) {
              let realUrl = ret.url.replace(
                Constants.OSS_URL,
                Constants.OSS_REAL_URL
              );
              ret.url = realUrl;
              _this.selectedImgList.push({
                imageId: nanoid(),
                url: ret.url,
                isUpload: true,
                content: fileName.split("\.")[0]
              });
              if (_this.imgFile.includes(fileType)) {
                _this.selectedImgList.at(-1).type = 1;
              } else if (_this.videoFile.includes(fileType)) {
                _this.selectedImgList.at(-1).type = 2;
              }
              _this.endUploadLength++;
              if (_this.endUploadLength == _this.startUploadLength) {
                _this.$Utils.notifySuccess("上传成功");
                _this.startUploadLength = 0;
                _this.endUploadLength = 0;
              }
              // }, 200)
              // 值回传
              option.response = ret;
              return ret;
            } else {
              option.onError("上传失败");
            }
          })
          .catch(function(err) {
            console.error(err);
          });
      } catch (error) {
        console.error(error);
        this.disabled = false;
        option.onError("上传失败");
        this.$error(error.message);
      }
    },
    // 选择或者清除图片
    hanldeSelectImg(val) {
      let index = this.selectedImgList.findIndex(
        item => item.imageId == val.imageId
      );
      let limit = this.limit;
      if (index == -1) {
        if (this.limit == 1) {
          this.selectedImgList = [val];
        } else if (this.selectedImgList.length + 1 <= limit) {
          this.selectedImgList.push(val);
        } else if (this.selectedImgList.length + 1 > limit) {
          this.$message.error("最多只可以选择" + limit + "张图片");
        }
      } else {
        this.selectedImgList.splice(index, 1);
      }
    },

    handlePreviewImg(el, index) {
      let videoNum = 0;
      // 这里需要过滤掉视频
      if (el == "elImage") {
        videoNum = this.list.slice(0, index).filter(item => item.type == 2)
          .length;
      } else if ((el = "elImage2")) {
        videoNum = this.selectedImgList
          .slice(0, index)
          .filter(item => item.type == 2).length;
      }
      index = index - videoNum;
      this.$refs[el][index].showViewer = true;
      this.$nextTick(() => {
        this.addHideToMask(this.$refs[el][index]);
      });
    },
    // 给每一个预览图片的遮罩层都添加一个点击事件，点击阴影可以取消
    addHideToMask(el) {
      const mask = el.$el.querySelector(".el-image-viewer__mask");
      if (mask) {
        let hide = () => {
          el.showViewer = false;
        };
        // 遮罩层增加点击事件，关闭预览
        mask.addEventListener("click", hide);
        // hook卸载事件，移除之前添加在mask元素的事件
        this.$once("hook:beforeMount", () => {
          mask && mask.removeEventListener("click", hide);
        });
      }
    },
    handleSizeChange(size) {
      this.page.pageSize = size;
      this.listData();
    },
    handleCurrentChange(val) {
      this.page.pageNo = val;
      this.listData();
    },
    // 根据搜索条件获取图片
    listData() {
      let params = {
        type: Number(this.filters.type),
        content: this.filters.content,
        pageNo: this.page.pageNo,
        pageSize: this.page.pageSize
      };
      if (this.userRole != 3) {
        params.businessId = this.filters.businessId;
      }
      this.loading = true;
      CommonImage.listCommonImage(params)
        .then(res => {
         this.list = res.data.list;
          this.page.pageTotal = res.data.total;
          this.page.totalPage = res.data.totalPage;
        })
        .finally(() => {
          this.loading = false;
        });
    },
    onSearch() {
      this.page.pageNo = 1;
      this.listData();
    },
    resetForm() {
      this.$refs.searchForm.resetFields();
      this.onSearch()
    },
    // 滚动加载
    handleScroll: throttle(function() {
      let el = document.getElementsByClassName("img-list")[0];
      if (el.scrollHeight - 10 < el.clientHeight + el.scrollTop) {
        this.page.pageNo++;
        this.listData(true);
      }
    }, 300),
    // 显示侧边抽屉
    handleShowDrawer() {
      this.showDrawer = true;
    }
  }
};
</script>
<style lang="scss" scoped>
.el-form-item {
  margin-bottom: 5px;
}

.el-tabs {
  &::v-deep .el-tabs__header {
    .el-tabs__nav-wrap {
      &::after {
        display: none !important;
      }
    }
  }
}

@mixin img-wrapper {
  .img-wrapper,
  .video-wrapper {
    position: relative;
    width: 150px;
    height: 150px;
    display: inline-block;
    // margin: 10px;
    cursor: pointer;

    .el-image {
      width: 100%;
      height: 100%;
    }

    .menu {
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      display: none;
      background-color: rgba(13, 10, 49, 0.7);

      i {
        color: white;
        font-size: 25px;
      }
    }

    .operate {
      position: absolute;
      width: 100%;
      top: 0;
      left: 0;
      display: none;
      background-color: rgba(13, 10, 49, 0.7);
      line-height: 50px;
      text-align: center;

      i {
        color: white;
        font-size: 25px;
      }
    }

    .check-wrapper {
      position: absolute !important;
      bottom: 0;
      right: 0;
      font-size: 30px;
      color: white;
      font-weight: 900;
      border: 20px solid #07c160;
      width: 0;
      height: 0;
      border-top: 20px solid transparent;
      border-left: 20px solid transparent;

      .el-icon-check {
        position: relative;
        bottom: 11px;
        right: 7px;
      }
    }

    &:hover .menu {
      display: block;

      & > div {
        line-height: 75px;
        text-align: center;

        &:hover {
          background-color: rgb(13, 10, 49);
        }
      }
    }

    &:hover .operate {
      display: block;
      background-color: rgb(13, 10, 49);
    }
  }
  .text {
    text-align: center;
    padding-top: 10px;
  }
}

.img-library {
  &::v-deep .el-dialog__body {
    padding-bottom: 10px !important;
  }

  .top-wrapper {
    display: flex;
    justify-content: space-between;

    .selected-img {
      font-size: 30px;
      cursor: pointer;

      i {
        position: relative;

        .dot {
          position: absolute;
          right: -8px;
          top: -3px;
          width: 20px;
          height: 20px;
          border-radius: 50%;
          background-color: red;
          color: white;
          font-size: 10px;
          text-align: center;
          line-height: 20px;
        }
      }
    }
  }

  .img-container {
    .img-list {
      display: grid;
      display: -ms-grid;
      grid-template-columns: repeat(auto-fill, 150px);
      -ms-grid-columns: repeat(auto-fill, 150px);
      grid-gap: 15px;
      justify-content: space-between;
      align-content: start;
      height: 500px;
      overflow: auto;
      border: 1px solid #f5f5f5;
      padding: 10px;
      @include img-wrapper;

      .empty {
        text-align: center;
        margin: 40px auto;
        color: #909399;
        font-size: 14px;
        grid-column: 1 / -1;
        -ms-grid-column: 1 / -1;
      }
    }
  }
}

.el-drawer__wrapper {
  .drawer-wrapper {
    height: 100%;
    position: relative;

    .cancel-back {
      display: none;
    }

    &:hover {
      .cancel-back {
        cursor: pointer;
        display: block;
        position: absolute;
        width: 60px;
        height: 60px;
        opacity: 0.5;
        background-color: grey;
        border-top-right-radius: 30px;
        border-bottom-right-radius: 30px;
        transform: translateX(-23px);
        top: 0;
        bottom: 0;
        margin: auto;
        line-height: 60px;
        text-align: end;
        font-size: 40px;
        box-sizing: border-box;
        padding-right: 3px;
        font-weight: 900;
        // .el-icon-arrow-right{

        // }
      }
    }

    .header {
      text-align: center;
      line-height: 40px;
      font-size: 23px;
    }

    .img-list {
      @include img-wrapper;
      .draggable {
        display: grid;
        display: -ms-grid;
        grid-template-columns: repeat(auto-fill, 140px);
        -ms-grid-columns: repeat(auto-fill, 140px);
        grid-gap: 10px;
        justify-content: space-between;
        align-content: start;
        padding: 10px;
        .img-wrapper,
        .video-wrapper {
          width: 140px !important;
          height: 140px !important;
          &:hover .menu {
            & > div {
              line-height: 60px !important;
            }
          }
        }
      }
    }
  }

  &::v-deep .el-drawer {
    width: 500px !important;
  }
}
</style>
